﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NBusiness.CodeDom.Compiler;
using System.Diagnostics;

namespace NBusiness.CodeDom
{
    public delegate void AssignmentLogicHandler(object sender, AssignmentLogicEventArgs e);
    [Serializable]
    public class AssignmentLogicEventArgs : EventArgs
    {
        private Stack<EntityElement> _elements;
        public Stack<EntityElement> Elements
        {
            get { return _elements; }
        }

        private EntityElementType _previous;
        public EntityElementType Previous
        {
            get { return _previous; }
        }

        public AssignmentLogicEventArgs(Stack<EntityElement> elements, EntityElementType previous)
        {
            _elements = elements;
            _previous = previous;
        }
    }

    public enum PostAssignmentAction
    {
        Continue,
        Stop
    }

    [Serializable]
    public sealed class AssignmentLogic
    {
        //private Regex _mustMatch;
        private EntityElementType _assignmentType;
        private AssignmentLogicHandler _handler;
        private PostAssignmentAction _postAssignmentAction;

        public EntityElementType AssignmentType
        {
            get { return _assignmentType; }
        }

        public PostAssignmentAction PostAssignmentAction
        {
            get { return _postAssignmentAction; }
        }

        public AssignmentLogic(EntityElementType assignmentType)
            : this(assignmentType, null, PostAssignmentAction.Continue)
        { }

        public AssignmentLogic(
            EntityElementType assignmentType, PostAssignmentAction postAssignmentAction)
            : this(assignmentType, null, postAssignmentAction)
        { }

        public AssignmentLogic(
            EntityElementType assignmentType, AssignmentLogicHandler handler)
            : this(assignmentType, handler, PostAssignmentAction.Continue)
        { }

        public AssignmentLogic(
            EntityElementType assignmentType,
            AssignmentLogicHandler handler,
            PostAssignmentAction postAssignmentAction)
        {
            _assignmentType = assignmentType;
            _handler = handler;
            _postAssignmentAction = postAssignmentAction;
        }

        internal bool Assign(Stack<EntityElement> elements, EntityElementType previous)
        {
            bool assign = false;

            if (_assignmentType.Expression.IsMatch(elements.Peek().Value))
            {
                foreach (EntityElementType type in _assignmentType.PreviousTypes)
                {
                    if (type == previous || type == EntityElementType.Any)
                    {
                        assign = true;
                        elements.Peek().Type = _assignmentType;
                        if (_handler != null)
                            _handler(this, new AssignmentLogicEventArgs(elements, previous));
                        break;
                    }
                }
            }
            return assign;
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder("assign " + _assignmentType.ToString() + " after ");
            for (int x = 0; x < _assignmentType.PreviousTypes.Length; x++)
            {
                if (x > 0) sb.Append(" | ");
                sb.Append(_assignmentType.PreviousTypes[x].ToString());
            }

            return sb.ToString();
        }
    }
}
